//
// Created by Felix on 24-5-16.
//

#include "CameraService.hpp"

oatpp::Object<CameraModel> CameraService::cameraModelFromCreateDto(
        const oatpp::Object<CameraCreateDto> &dto
) {
    auto model = CameraModel::createShared();
    model->id = nullptr;
    model->title = dto->title;
    model->pullUrl = dto->pullUrl;
    model->pushUrl = dto->pushUrl;
    model->model = dto->model;
    model->status = 1;
    model->createTime = getCurrentTime();
    model->updateTime = model->createTime;
#ifdef __APPLE__
    model->deleteTime = 0LL;
#else
    model->deleteTime = 0L;
#endif
    return model;
}

oatpp::Object<CameraResponseDto> CameraService::cameraResponseDtoFromModel(
        const oatpp::Object<CameraModel> &model
) {
    auto dto = CameraResponseDto::createShared();
    dto->cameraId = model->id;
    dto->title = model->title;
    dto->pullUrl = model->pullUrl;
    dto->pushUrl = model->pushUrl;
    dto->model = model->model;
    dto->status = model->status;
    dto->createTime = model->createTime;
    dto->updateTime = model->createTime;
    dto->deleteTime = model->deleteTime;
    return dto;
}

oatpp::Object<CameraModel> CameraService::cameraModelFromUpdateDetailsDto(
        const oatpp::Object<CameraUpdateDetailsDto> &dto
) {
    auto model = CameraModel::createShared();
    model->id = dto->cameraId;
    model->title = dto->title;
    model->pullUrl = dto->pullUrl;
    model->pushUrl = dto->pushUrl;
    model->model = dto->model;
    model->status = dto->status;
    model->updateTime = getCurrentTime();
    return model;
}

oatpp::Object<CameraModel> CameraService::cameraModelFromUpdateStatusDto(
        const oatpp::Object<CameraUpdateStatusDto> &dto
) {
    auto model = CameraModel::createShared();
    model->id = dto->cameraId;
    model->status = dto->status;
    model->updateTime = getCurrentTime();
    return model;
}

oatpp::Object<CameraResponseDto> CameraService::createCamera(
        const oatpp::Object<CameraCreateDto> &dto
) {
    auto dbResult = iCameraDatabase->createCamera(cameraModelFromCreateDto(dto));
    OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, dbResult->getErrorMessage())

    auto result = dbResult->fetch<oatpp::Vector<oatpp::Object<CameraModel>>>();
    OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown Error")

    return cameraResponseDtoFromModel(result[0]);
}

oatpp::Object<CameraResponseDto> CameraService::updateCameraDetails(
        const oatpp::Object<CameraUpdateDetailsDto> &dto
) {
    auto dbResult = iCameraDatabase->updateCameraDetails(cameraModelFromUpdateDetailsDto(dto));
    OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, dbResult->getErrorMessage())

    auto result = dbResult->fetch<oatpp::Vector<oatpp::Object<CameraModel> > >();
    OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown Error")

    return cameraResponseDtoFromModel(result[0]);
}

oatpp::Object<CameraResponseDto> CameraService::updateCameraStatus(
        const oatpp::Object<CameraUpdateStatusDto> &dto
) {
    auto dbResult = iCameraDatabase->updateCameraStatus(cameraModelFromUpdateStatusDto(dto));
    OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, dbResult->getErrorMessage())

    auto result = dbResult->fetch<oatpp::Vector<oatpp::Object<CameraModel>>>();
    OATPP_ASSERT_HTTP(result->size() == 1, Status::CODE_500, "Unknown Error")

    return cameraResponseDtoFromModel(result[0]);
}

oatpp::Object<CameraResponseDto> CameraService::getCameraById(
        const oatpp::Int32 &cameraId
) {
    auto dbResult = iCameraDatabase->getCameraById(cameraId);
    OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, dbResult->getErrorMessage())

    auto result = dbResult->fetch<oatpp::Vector<oatpp::Object<CameraModel>>>();
    if (!result->empty()) {
        return cameraResponseDtoFromModel(result[0]);
    }

    return nullptr;
}

oatpp::Object<PageResponseDto<oatpp::Object<CameraResponseDto>>> CameraService::getAllCamera(
        const oatpp::Int32 &page, const oatpp::Int32 &pageSize,
        const oatpp::Object<CameraServiceGetAllCameraQueryDto> &queryDto
) {
    oatpp::Int32 p = std::max(page, oatpp::Int32(1));
    oatpp::Int32 offset = (p - 1) * pageSize;
    oatpp::Int32 limit = std::min(std::max(pageSize, oatpp::Int32(1)), oatpp::Int32(50));

    std::unordered_map<oatpp::String, oatpp::Void> params = {
            {"offset", offset},
            {"limit",  limit},
    };
    std::vector<std::string> queryLines = {
            "SELECT COUNT(id)",
            "FROM camera",
            "WHERE delete_time = 0",
    };
    if (!queryDto->keyWords->empty()) {
        params["keyWords"] = oatpp::String("%" + queryDto->keyWords + "%");
        queryLines.emplace_back("AND (title LIKE :keyWords OR pull_url LIKE :keyWords OR push_url LIKE :keyWords)");
    }
    if (queryDto->status > 0) {
        params["status"] = queryDto->status;
        queryLines.emplace_back("AND status = :status");
    }
    oatpp::String query = joinWithSpaces(queryLines);
    auto dbCountResult = iCameraDatabase->executeQuery(query, params);
    OATPP_ASSERT_HTTP(dbCountResult->isSuccess(), Status::CODE_500, dbCountResult->getErrorMessage())
    auto total = dbCountResult->fetch<oatpp::Vector<oatpp::Vector<oatpp::Int32>>>()[0][0];

    queryLines[0] = "SELECT id AS camera_id, title, pull_url, push_url, model, status, create_time, update_time, delete_time";
    queryLines.emplace_back("ORDER BY id DESC");
    queryLines.emplace_back("LIMIT :limit OFFSET :offset");
    query = joinWithSpaces(queryLines);
    // 动态SQL查询
    // OATPP_LOG("")
    // executeQuery执行SQL查询
    auto dbResult = iCameraDatabase->executeQuery(query, params);
    OATPP_ASSERT_HTTP(dbResult->isSuccess(), Status::CODE_500, dbResult->getErrorMessage())
    auto items = dbResult->fetch<oatpp::Vector<oatpp::Object<CameraResponseDto>>>();

    auto dto = PageResponseDto<oatpp::Object<CameraResponseDto> >::createShared();
    dto->current = p;
    dto->pageSize = limit;
    dto->total = total;
    dto->items = items;

    return dto;
}
